/* 
 * File:   Node.cpp
 * Author: James
 * 
 * Created on November 19, 2010, 4:12 PM
 */

#include "Node.h"


Node::Node(bool receiv) {


  if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
      perror("Socket err");
    //cout << "Failed to initialize socket fd... terminating" << endl;
    exit(-1);
  }
  
  addr.sin_family = AF_INET;     // host byte order
  addr.sin_addr.s_addr = htonl(INADDR_ANY); // my address
  memset(&(addr.sin_zero), '\0', 8); // zero the rest of the struct

  if (receiv) {
      int yes = 1;
        // lose the pesky "Address already in use" error message
        if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
            perror("Setsockopt err");
            exit(-1);
        }

        addr.sin_port = htons(RECEIVER_PORT);
        if (bind(socket_fd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
            perror("Bind err");
         exit(-1);
        }
        if (listen(socket_fd, 5) == -1) {
            perror("Listen err");
            exit(-1);
        } else {
            cout << "Listening on socket " << socket_fd
                    << ", port " << ntohs(addr.sin_port) << endl;
        }

    } else {
        //port = 31338;
        //addr.sin_port = htons(port);   // designated port

    }
  

  




  

}

Node::Node(const Node& orig) {
    cout << "don't use the node copy constructor" << endl;
}

Node::~Node() {
    cout << "Node deconstructor" << endl;
    delete (sockaddr_in *)&addr;
}

struct sockaddr_in* Node::getAddr() {
    return &addr;
}

int Node::conn(struct sockaddr_in* host) {
    if (connect(socket_fd, (struct sockaddr *)host, sizeof(struct sockaddr)) == -1) {
        perror("Connect err");
      //cout << "Failed to connect with host... terminating" << endl;
      return -1;
    } else {
        cout << "Connected to host: " << inet_ntoa(host->sin_addr) << " - port: "
                << ntohs(host->sin_port) << endl;
        return 0;
    }
}
int Node::acc(sockaddr_in* client) {
    int sin_size = sizeof(struct sockaddr_in);
    
    if ((new_fd = accept(socket_fd, (struct sockaddr *)client, &sin_size)) == -1) {
        perror("Accept err");
        //cout << "Failed to accept socket... terminating" << endl;
        return -1;
    } else {
        
        cout << "Accepted client: " << inet_ntoa(client->sin_addr) << " - port: "
                << ntohs(client->sin_port) << endl;
        cout << "New fd for this client: " << new_fd << endl;
        return 0;
    }
}

void Node::closeFD(char fd) {
    cout << "Closing fd... " << fd << endl;
    if (fd == 's') { // close socket_fd
        close(socket_fd);
    } else if (fd == 'n') { // close new_fd
        close(new_fd);
    }
}

// send
int Node::sendMsg(char* msg, char fd) {
    int len = strlen(msg);
    
    int fd_send;

    if (fd == 's') { // send to socket_fd: use for initiator
        fd_send = this->socket_fd;
    } else if (fd == 'n') { // send to new_fd: use for recievers
        fd_send = this->new_fd;
    } else {
        cout << "Invalid use of Node::send() -> 2nd argument must be 's' or 'n'"
                << endl;
        return -1;
    }

    // handle partial sends

    int total = 0; // how many bytes we’ve sent
    int bytesleft = len; // how many we have left to send
    int bytes_sent;
    while(total < len) {
        bytes_sent = send(fd_send, msg+total, bytesleft, 0);
        if (bytes_sent == -1) {
            perror("Send err");
            return -1;
        }

        total += bytes_sent;
        bytesleft -= bytes_sent;
    } 
    cout << "Message sent: " << msg << endl;
    
    return 0;
}



// receive
int Node::receive(char* msg, int maxBytes, char fd) {
    int fd_recv;
    if (fd == 's') { // socket_fd
        fd_recv = socket_fd;
    } else if (fd == 'n') { // new_fd
        fd_recv = new_fd;
    }
    cout << "Attempting to recieve from fd: " << fd_recv << " with a max size of "
            << maxBytes << endl;
    int numbytes;
    if ((numbytes = recv(fd_recv, msg, maxBytes-1, 0)) == -1) {
        perror("Receive err");
        return -1;
    } else {
    msg[numbytes] = '\0';



    return 0;
    }
}

